﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;

namespace CommTest
{

    public partial class FormMain : Form
    {
        protected int[] baudrates = { 230400, 115200, 57600, 38400, 19200, 9600, 4800, 2400, 1200, 300 };
        protected const int defaultBaudrate = 9600;
        protected SerialPort serial;
        protected int sendCount = 0;
        protected int recvCount = 0;
        //protected static FormMain formInstance;
        
        public delegate void OnRecv();
        public OnRecv serialRecvDelegate;

        public FormMain() {
            InitializeComponent();
        }

        private void FormMain_Load(object sender, EventArgs e) {
            //串口号列表
            serialPortCmb.Items.Clear();
            string[] serialPortNames = SerialPort.GetPortNames();
            Array.Sort(serialPortNames);
            for (int i = 0; i < serialPortNames.Length; i++)
                serialPortCmb.Items.Add(serialPortNames[i]);
            serialPortCmb.SelectedIndex = 0;
            //波特率
            serialBaudrateCmb.Items.Clear();
            for (int j = 0; j < baudrates.Length; j++) {
                int baudrate = baudrates[j];
                serialBaudrateCmb.Items.Add(baudrate);
                if (baudrate == defaultBaudrate)
                    serialBaudrateCmb.SelectedIndex = j;
            }
            //串口对象
            if (serial == null) {
                serial = new SerialPort();
                serial.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
            }
            //窗体对象
            //formInstance = this;
            serialRecvDelegate = new OnRecv(onSerialRecv);
        }

        private void openSerialBtn_Click(object sender, EventArgs e) {
            if (serial.IsOpen)
                serial.Close();
            else {
                try {
                    serial.PortName = (string)serialPortCmb.SelectedItem;
                    serial.BaudRate = (int)serialBaudrateCmb.SelectedItem;
                    serial.Open();
                }
                catch (Exception exception) {
                    MessageBox.Show(exception.Message);
                }
            }
            if (serial.IsOpen) {
                serialPortCmb.Enabled = false;
                serialBaudrateCmb.Enabled = false;
                openSerialBtn.Text = "关闭串口";
            }
            else {
                serialPortCmb.Enabled = true;
                serialBaudrateCmb.Enabled = true;
                openSerialBtn.Text = "打开串口";
            }
        }

        private void sendLineBtn_Click(object sender, EventArgs e) {
            if (!serial.IsOpen) {
                MessageBox.Show("请先打开串口！");
                return;
            }
            string textToSend = toSendTxt.Text;
            while (textToSend.Length > 0) {
                int linePos = textToSend.IndexOf("\n");
                if (linePos == 0) {
                    textToSend = textToSend.Remove(0, 1);
                    toSendTxt.Text = textToSend;
                    continue;
                }
                else if (linePos < 0) {
                    sendLine(textToSend);
                    toSendTxt.Text = "";
                    break;
                }
                else {
                    sendLine(textToSend.Substring(0, linePos));
                    if (linePos + 1 < textToSend.Length)
                        toSendTxt.Text = textToSend.Substring(linePos + 1);
                    else
                        toSendTxt.Text = "";
                    break;
                }
            }
        }

        private void sendLine(string line) {
            sentTxt.Text = line;
            byte[] buffer = new byte[1024];
            int bytes = TextUtility.hexscan(line, buffer, buffer.Length);
            if (bytes == buffer.Length)
                MessageBox.Show(String.Format("本行太长，单次最多发送{0}字节。", buffer.Length));
            else if (bytes > 0) {
                serial.Write(buffer, 0, bytes);
                sendCount += bytes;
                sendCountLbl.Text = String.Format("{0}字节", sendCount);
            }
        }

        public void onSerialRecv() {
            byte[] recvBuffer = new byte[1024];
            int bytes = 0;
            do {
                bytes = serial.Read(recvBuffer, 0, recvBuffer.Length);
                if (bytes > 0)
                    onSerialRead(recvBuffer, bytes);
            }
            while (bytes == recvBuffer.Length);
        }

        private void onSerialRead(byte[] buffer, int bytes) {
            recvCount += bytes;
            StringBuilder recv = new StringBuilder(bytes * 3);
            for (int i = 0; i < bytes; i++)
                recv.AppendFormat("{0,3:X2}", buffer[i]);
            recvTxt.Text += String.Format("[{0}]{1}{2}", DateTime.Now.ToString("HH:mm:ss:fff"), recv.ToString(), Environment.NewLine);
            recvTxt.Select(recvTxt.Text.Length, 1);
            recvTxt.ScrollToCaret();
            recvCountLbl.Text = String.Format("{0}字节", recvCount);
        }

        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) {
            if (e.EventType == SerialData.Eof)
                return;
            this.Invoke(serialRecvDelegate);
        }

        private void sendAgainBtn_Click(object sender, EventArgs e) {
            if (!serial.IsOpen) {
                MessageBox.Show("请先打开串口！");
                return;
            }
            sendLine(sentTxt.Text);
        }

        private void clearRecvBtn_Click(object sender, EventArgs e) {
            recvTxt.Text = "";
        }

        private void resetCountBtn_Click(object sender, EventArgs e) {
            sendCount = 0;
            recvCount = 0;
            sendCountLbl.Text = "0字节";
            recvCountLbl.Text = "0字节";
        }

        private void openFileBtn_Click(object sender, EventArgs e) {
            OpenFileDialog openFileDlg = new OpenFileDialog();
            if (openFileDlg.ShowDialog() == DialogResult.OK) {
                StringBuilder sb = new StringBuilder();
                StreamReader sr = new StreamReader(openFileDlg.OpenFile());
                string line = null;
                do {
                    line = sr.ReadLine();
                    sb.AppendLine(line);
                }
                while (line != null);
                toSendTxt.Text = sb.ToString();
                sr.Close();
            }
        }
    }
}
